package util

import (
	"bytes"
	"encoding/base64"
	"encoding/gob"
	"io"
	"strings"

	"github.com/cosiner/zerver"
)

type (
	IResourceMaster interface {
		Send(resp io.Writer, key string, value interface{}) error
		Recieve(req io.Reader, v interface{}) error
	}

	gobBase64ResourceMaster struct {
		zerver.ResourceMaster
	}
)

var (
	GobBase64ResourceMaster = gobBase64ResourceMaster{
		ResourceMaster: zerver.ResourceMaster{
			Marshaler: zerver.MarshalFunc(gobBase64Marshal),
			Unmarshal: base64GobUnmarshal,
		},
	}

	replacer = strings.NewReplacer(
		"%2F", "/",
		"%3D", "=",
	)
)

func gobBase64Marshal(val interface{}) ([]byte, error) {
	buf := bytes.NewBuffer(nil)
	enc := gob.NewEncoder(buf)
	if err := enc.Encode(val); err == nil {
		return []byte(base64.StdEncoding.EncodeToString(buf.Bytes())), nil
	} else {
		return nil, err
	}
}

func base64GobUnmarshal(src []byte, val interface{}) error {
	if dst, err := base64.StdEncoding.DecodeString(replacer.Replace(string(src))); err == nil {
		dec := gob.NewDecoder(bytes.NewBuffer(dst))
		return dec.Decode(val)
	} else {
		return err
	}
}

func (r gobBase64ResourceMaster) Send(resp io.Writer, _ string, value interface{}) (err error) {
	var bs []byte
	if bs, err = r.Marshal(value); err == nil {
		r.Pool(bs)
		_, err = resp.Write(bs)
	}
	return err
}
